/*
 * Copyright 2010 - Jeremie Brebec
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.jb.sharedbills.client.form;

import java.util.ArrayList;
import java.util.List;

import org.jb.sharedbills.client.resources.Resources;
import org.jb.sharedbills.client.stores.EventSaver;
import org.jb.sharedbills.client.stores.MemberStore;
import org.jb.sharedbills.client.stores.EventSaver.SaveStateListener;
import org.jb.sharedbills.client.stores.EventSaver.State;
import org.jb.sharedbills.shared.model.Member;
import org.jb.sharedbills.shared.model.logic.EventConstraints;

import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MessageBoxEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Dialog;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.grid.AggregationRowConfig;
import com.extjs.gxt.ui.client.widget.grid.CellEditor;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.EditorGrid;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
import com.extjs.gxt.ui.client.widget.grid.GridSelectionModel;
import com.extjs.gxt.ui.client.widget.grid.SummaryType;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.inject.Inject;

/**
 * 
 * @author jeremie
 *
 */
public class MemberPanel extends ContentPanel implements SaveStateListener {

	/**
	 * 
	 * @param members
	 */
	@Inject
	public MemberPanel( MemberStore store, EventSaver eventSaver ) {
		
		this.store = store;
		this.eventSaver = eventSaver;
		
		setHeaderVisible(false);
		setBorders(false);
		setLayout( new FitLayout() );
		
		setTopComponent( createToolbar() );

		eventSaver.addListener(this);
		
		add( createGrid() );
		
	}
	
	/**
	 * 
	 * @return
	 */
	private Grid<BeanModel> createGrid() {
		List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
		ColumnConfig columnName = new ColumnConfig("name","Nom",100);
		TextField<String> text = new TextField<String>();  
	    text.setAllowBlank(false);  
	    columnName.setEditor(new CellEditor(text)); 
	    
	    final NumberFormat numberFormat = NumberFormat.getFormat("0.00");
	    final String constColumnStyle = "background-color: #F3F3F3;";
	    
		ColumnConfig columnAmount = new ColumnConfig("maxAmount", "A payé", 80);
		columnAmount.setAlignment(HorizontalAlignment.RIGHT);  
		columnAmount.setNumberFormat(numberFormat);
		columnAmount.setStyle( constColumnStyle );
		
		ColumnConfig columnUsed = new ColumnConfig("used", "Coût", 80 );
		columnUsed.setNumberFormat(numberFormat);
		columnUsed.setAlignment(HorizontalAlignment.RIGHT); 
		columnUsed.setStyle( constColumnStyle );
		
		ColumnConfig columnBalance = new ColumnConfig("balance", "Balance", 80 );
		columnBalance.setNumberFormat(numberFormat);
		columnBalance.setAlignment(HorizontalAlignment.RIGHT); 
		columnBalance.setStyle( constColumnStyle );
		columnBalance.setRenderer( new GridCellRenderer<BeanModel>() {

			@Override
			public Object render(BeanModel model, String property,
					ColumnData config, int rowIndex, int colIndex,
					ListStore<BeanModel> store, Grid<BeanModel> grid) {
				double val = (Double) model.get(property);  
		        String style = val < 0 ? "red" : "green";  
		        return "<span style='color:" + style + "'>" + numberFormat.format(val) + "</span>";  
			}
		});

		AggregationRowConfig<BeanModel> averages = new AggregationRowConfig<BeanModel>();  
	    averages.setHtml("name", "Moyenne");  
	      
	    // with summary type and format  
	    averages.setSummaryType("amount", SummaryType.AVG);  
	    averages.setSummaryFormat("amount", numberFormat );
	    averages.setSummaryType("used", SummaryType.AVG);  
	    averages.setSummaryFormat("used", numberFormat );
		
		columns.add(columnName);
		columns.add(columnAmount);
		columns.add(columnUsed);
		columns.add(columnBalance);
		
		ColumnModel cm = new ColumnModel(columns);
	    cm.addAggregationRow(averages);  

		grid = new EditorGrid<BeanModel>(store,cm);
		grid.setSelectionModel( new GridSelectionModel<BeanModel>() );
		grid.setAutoExpandColumn("name");
		
		grid.addListener(Events.BeforeEdit, new Listener<GridEvent<BeanModel>>() {
			@Override
			public void handleEvent(GridEvent<BeanModel> be) {
				if (eventSaver.getState() == State.LOCKED) {
					be.setCancelled(true);
				}
			}
		});
		
		return grid;
	}
	
	/**
	 * 
	 * @return
	 */
	private ToolBar createToolbar() {
		ToolBar tb = new ToolBar();
		
		addBtn = new Button("Créer", AbstractImagePrototype.create(Resources.INSTANCE.add()));
		addBtn.addSelectionListener( new SelectionListener<ButtonEvent>() {
			
			@Override
			public void componentSelected(ButtonEvent ce) {
				Member m = new Member();
				m.setName("");
				
				grid.stopEditing();
				store.getEvent().getMembers().add(m);
				grid.startEditing(store.getCount() - 1, 0 );
			}
		});
		addBtn.disable();
		tb.add( addBtn );
		
		deleteBtn = new Button("Supprimer", AbstractImagePrototype.create(Resources.INSTANCE.delete()));
		deleteBtn.disable();
		deleteBtn.addSelectionListener( new SelectionListener<ButtonEvent>() {

			@Override
			public void componentSelected(ButtonEvent ce) {
				BeanModel m = grid.getSelectionModel().getSelectedItem();
				if (m == null) {
					MessageBox dlg = MessageBox.alert("Suppression", "Aucune ligne sélectionnée" , new Listener<MessageBoxEvent>() {
						@Override
						public void handleEvent(MessageBoxEvent be) {}
					});
					dlg.show();
					return;
				}

				final Member member = m.getBean();
				if (!EventConstraints.checkMemberDeletion(store.getEvent(), member)) {
					StringBuilder b = new StringBuilder();
					b.append( "Impossible de supprimer le participant <i>" );
					b.append( member.getName() );
					b.append( "</i><br>Vérifiez qu'aucune dépense n'a été payé par cette personne.");
					MessageBox dlg = MessageBox.alert("Suppression", b.toString() , new Listener<MessageBoxEvent>() {
						@Override
						public void handleEvent(MessageBoxEvent be) {}
					});
					dlg.setIcon(MessageBox.ERROR);
					dlg.show();
					dlg.getDialog().setWidth( 400 );
					return;
				}
				
				MessageBox dlg = MessageBox.confirm("Suppression", "Voulez-vous vraiment supprimer ces participants ?", new Listener<MessageBoxEvent>() {

					@Override
					public void handleEvent(MessageBoxEvent be) {
						if (Dialog.YES.equals( be.getButtonClicked().getItemId())) {
							store.getEvent().getMembers().remove( member );
						}
					}
				});
				dlg.show();
			}
		});
		tb.add( deleteBtn );
		
		return tb;
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.jb.sharedbills.client.stores.EventSaver.SaveStateListener#onStateChange(org.jb.sharedbills.client.stores.EventSaver.State)
	 */
	@Override
	public void onStateChange(State state) {
		if (state == State.COMMIT) {
			store.commitChanges();
		}
		
		if (state != State.LOCKED) {
			addBtn.enable();
			deleteBtn.enable();
		}
	}
	
	private EditorGrid<BeanModel> grid;
	
	private MemberStore store;

	private final EventSaver eventSaver;

	private Button addBtn;
	private Button deleteBtn;

}
